package cn.ywyself.extend.directive;

import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.ParseException;
import com.jfinal.template.stat.Scope;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * 对内容进行URL编码<br>
 * 使用：<br>
 * <li>参数1：需要编码的字符串</li>
 * <li>参数2：编码格式，缺省值为'UTF-8'</li>
 *
 * @author : ywyself
 * @created : 2018-08-01 15:09
 */
public class UrlEncodeDirective extends Directive {

    private int paraNum;
    private Expr textExpr;
    private Expr charsetExpr;

    @Override
    public void setExprList(ExprList exprList) {
        this.paraNum = exprList.length();
        if (paraNum == 0) {
            throw new ParseException("Wrong number parameter of #urlEncode directive, one parameters allowed at least", location);
        } else if (paraNum == 1) {
            this.textExpr = exprList.getExpr(0);
            this.charsetExpr = null;
        } else if (paraNum == 2) {
            this.textExpr = exprList.getExpr(0);
            this.charsetExpr = exprList.getExpr(1);
        } else {
            throw new ParseException("Wrong number parameter of #urlEncode directive, two parameters allowed at most", location);
        }
    }

    @Override
    public void exec(Env env, Scope scope, Writer writer) {
        Object value = textExpr != null ? textExpr.eval(scope) : null;
        if (value == null) {
            value = "";
        } else if (!(value instanceof String)) {
            throw new TemplateException("The first parameter pattern of # directive must be String", location);
        }
        // 一个参数：需要编码的字符串
        if (paraNum == 1) {
            output(writer, (String) value);
        }
        // 两个参数：需要编码的字符串，编码格式
        else if (paraNum == 2) {
            Object charset = charsetExpr.eval(scope);
            if (!(charset instanceof String)) {
                throw new TemplateException("The second parameter pattern of # directive must be String", location);
            }
            output(writer, (String) value, (String) charset);
        }
    }

    private void output(Writer writer, String text) {
        output(writer, text, "UTF8");
    }

    private void output(Writer writer, String text, String charset) {
        try {
            text = URLEncoder.encode(text, charset);
        } catch (UnsupportedEncodingException ignored) {
        }
        write(writer, text);
    }
}
